package ie.flax.flaxengine.client.Graphic;
import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.event.dom.client.LoadEvent;
import com.google.gwt.event.dom.client.LoadHandler;
import com.google.gwt.user.client.Window;
import com.kfuntak.gwt.json.serialization.client.JsonSerializable;
import ie.flax.flaxengine.client.FLog;
import ie.flax.flaxengine.client.FVector;
import ie.flax.flaxengine.client.FlaxEngine;
/**
* This class handles the sprite for objects, like NPC , Characters etc.
* It handles both non-animated and animated sprites.
* @author Ciar�n McCann
*
*/
public class Sprite implements JsonSerializable {
private transient FImage image;
private transient int currentFrame; //The current frame, x pos across the image
private transient int frameCount; //Number of frames across
private transient AnimationState animationState; //This holds the animated row
private transient double timeSinceLastFrame;
private String imagePath;
private int frameWidth; // size of each frame eg 32 * 32
private int frameHeight;
/**
* The path is the string URL to the image
*
* Non-Animated Sprites:
* If frame width and height equal 0 then its an non animated sprite
*
* Animated Sprites
* Once the frame with and height is greater then 0, the sprite is
* treated as an animated sprite
*
* @param Path
* @param frameWidth
* @param frameHeight
*/
public Sprite(final String path, final int frameWidth, final int frameHeight)
{
this.frameHeight = frameHeight;
this.frameWidth = frameWidth;
this.imagePath = path;
init();
}
/**
* FIXME CIARAN - Get the serializer to call a method of name init() if the class type implements a certain interface
* or go crazy and try and get rid of the end for public get and sets and have the system load from just the construct paramters.
*
*
*/
/**
* This method most be called in constructor and also after deserailzation
*/
public void init()
{
Graphic.getSingleton().loadImage(imagePath).addLoadHanderl(new LoadHandler() {
@Override
public void onLoad(LoadEvent event) {
image = Graphic.getSingleton().getFImage(imagePath);
//If the frame width and height are not specified then its not an animated sprite
if(frameWidth+frameHeight != 0)
{
frameCount = (image.getImage().getWidth()/frameWidth)-1;
currentFrame = 0;
animationState = AnimationState.DOWN; //default to idle state
}
}
});
}
@Deprecated
public Sprite()
{
animationState = AnimationState.IDE;
}
/**
* This draws the sprite, if its an animated sprite or just a simple image
*/
public void draw(Canvas drawingSpace, FVector position)
{
if(image.isLoaded())
{
//If its frameheight is not specified then its not an animated sprite
if(frameHeight != 0)
{
if(animationState == AnimationState.IDE )
{
nextFrame(); //IDLE status update
//This may fuck up as its tied to the refresh rate of the canvas
}
// TODO CIARAN - optimize this drawing as more entites are added
drawingSpace.getContext2d().drawImage(image.getImage(),currentFrame*frameWidth,(animationState.index*frameHeight), frameWidth, frameHeight, position.x-FlaxEngine.camera.getX(), position.y-FlaxEngine.camera.getY(),frameWidth, frameHeight);
//FLog.error("sprite xs " + currentFrame*frameWidth + " sy " + animationState.index*frameHeight);
}
else{
//Non-animated image
drawingSpace.getContext2d().drawImage(image.getImage(), position.x-FlaxEngine.camera.getX(), position.y-FlaxEngine.camera.getY(),image.getImage().getWidth(), image.getImage().getHeight());
}
}
}
/**
* Sets the row of the sprite image, also if the current state isnt the same as the one beening passed in
* it will reset the currentframe count
* @param state
*/
public void setAnimationState(AnimationState state)
{
if(this.animationState != state)
{
this.animationState = state;
this.currentFrame = 0;
}
}
/**
* Moves the animation across the image row to the next frame
* and loops back once it reaches the end.
*/
public void nextFrame()
{
if (timeSinceLastFrame >= 1500) {
if (currentFrame < frameCount) {
currentFrame++;
} else {
currentFrame = 3; // FIXME set back to zero, only for spefic
// sprite
}
timeSinceLastFrame = 0;
}
}
//Different Y values for the animations
public enum AnimationState {
IDE(0),
UP(2),
DOWN(0),
LEFT(1),
RIGHT(3);
private final int index;
AnimationState(int index)
{
this.index = index;
}
public int index(){
return index;
}
}
/**
* DO NOT USE THIS METHOD -This method only exist so that JSON serialization
* can work Using this method is at your own risk and will most likely break
* your code in RUNTIME!!
*
*/
@Deprecated
public void setCurrentFrame(int currentFrame) {
this.currentFrame = currentFrame;
}
/**
* DO NOT USE THIS METHOD -This method only exist so that JSON serialization
* can work Using this method is at your own risk and will most likely break
* your code in RUNTIME!!
*
*/
@Deprecated
public void setFrameWidth(int frameWidth) {
this.frameWidth = frameWidth;
init();
}
/**
* DO NOT USE THIS METHOD -This method only exist so that JSON serialization
* can work Using this method is at your own risk and will most likely break
* your code in RUNTIME!!
*
*/
@Deprecated
public int getFrameWidth() {
return frameWidth;
}
/**
* DO NOT USE THIS METHOD -This method only exist so that JSON serialization
* can work Using this method is at your own risk and will most likely break
* your code in RUNTIME!!
*
*/
@Deprecated
public int getFrameHeight() {
return frameHeight;
}
/**
* DO NOT USE THIS METHOD -This method only exist so that JSON serialization
* can work Using this method is at your own risk and will most likely break
* your code in RUNTIME!!
*
*/
@Deprecated
public void setFrameHeight(int frameHeight) {
this.frameHeight = frameHeight;
}
public AnimationState getAnimationState() {
return animationState;
}
public String getImagePath() {
return imagePath;
}
public void setImagePath(String imagePath) {
this.imagePath = imagePath;
}
public void update(double deltaTime) {
timeSinceLastFrame += deltaTime;
}
}